feat(desktop): add host-bound folder references to the composer - #4097
feat(desktop): add host-bound folder references to the composer#4097sunrioa wants to merge 11 commits into
Conversation
Add a separate Reference folder action and removable directory chips without changing the selected Project, Session cwd, or filesystem permissions. Prepare a bounded one-level directory observation at message admission and preserve it with Host-bound references through persistence, queued submission, and replay. Bump protocol compatibility to 57 and cover the contract with regression tests and Desktop E2E. Generated-by: OpenAI Codex
Close execution and artifact stores before releasing the fixture owner and removing its temporary root. Assert SQLite lease release with and without artifacts, and record explicit Windows exclusions for privileged file symlinks and Linux directory-descriptor mounts. Generated-by: OpenAI Codex
Release the standalone linked-child test's execution stores before its root owner and temporary directory. Assert that the shared SQLite connection is closed so POSIX runs also detect the Windows teardown regression. Generated-by: OpenAI Codex
Keep listing deadlines and expected directory request rejections from draining the Runtime Host while preserving fail-stop handling for unexpected failures. Validate Glob enumeration roots within the existing execution boundary, and count escaped entries against the shared byte budget. Cover timeout, cancellation, invalid references, unreadable roots, and subsequent message admission with regression tests. Generated-by: OpenAI Codex
Merge main at 3b9a470 while preserving Host-bound directory references and upstream session, retry, and redaction changes. Advance the compatibility epoch to 62, refresh generated inventories, and cover merged protocol and conversation-copy behavior. Generated-by: OpenAI Codex
Astro-Han
left a comment
There was a problem hiding this comment.
Thanks for taking this all the way through the Runtime Host, persistence, replay, and Desktop UI layers. The underlying problem is real: a user should be able to reference a directory without uploading every file or changing the Session working directory.
I think the first version could be substantially simpler, though.
The PR already preserves a good core authority — the Host-bound { hostId, path } reference — but it then eagerly scans one directory level during admission and carries a frozen listing through queueing, replay, and regeneration. That introduces two views of the same directory: the submission-time snapshot and the live filesystem later observed through Glob/Read.
Could we narrow the first slice to:
- persist and present only the Host-bound directory reference;
- let the Agent inspect it on demand using the existing Glob/Read tools;
- continue relying on the existing Runtime Host boundary and permission flow?
This would avoid a second filesystem observation path and remove much of the preparation, timeout, frozen-listing, replay, and coordinator machinery. If real usage later shows that Agents routinely fail to inspect referenced directories, an eager bounded preview could still be added from evidence rather than assumed up front.
There is also one concrete P2 in the current implementation: the five-second abort reaches the managed worker path, but the local bypass/full-access path does not pass the signal into nodeGlob. A slow or unavailable network mount can therefore keep the submission blocked well past the intended timeout. The smaller path-only design would avoid needing this admission-time timeout altogether.
This is intended as a simplification suggestion, not a request for a parallel implementation. The directory reference should remain the single authority either way.
Review analysis was assisted by Codex and independent @reviewer agents; Astro-Han evaluated the proposed authority boundary, reachability, and simplification and owns this comment.
中文对照
谢谢你把这个功能完整地贯通到 Runtime Host、持久化、重放和 Desktop UI。它要解决的问题是真实的:用户应该能够引用一个目录,而不需要上传其中的每个文件,也不需要改变 Session 的工作目录。
不过我认为第一版可以明显更简单。
当前 PR 已经保留了一个很好的核心 authority——Host-bound 的 { hostId, path } 引用;但随后又在 admission 阶段主动扫描一层目录,并让冻结的 listing 参与排队、重放和重新生成。这会产生同一目录的两种视图:提交时的快照,以及 Agent 后续通过 Glob/Read 看到的实时文件系统。
是否可以把第一版收敛为:
- 只持久化并呈现 Host-bound 的目录引用;
- 让 Agent 按需使用现有 Glob/Read 工具检查目录;
- 继续复用现有 Runtime Host boundary 和权限流程?
这样可以避免第二条文件系统观察路径,并删除大量 preparation、timeout、冻结 listing、重放和 coordinator 机制。如果真实使用证明确实有很多 Agent 不会主动检查被引用的目录,我们再基于证据增加有限的主动预览也不迟。
当前实现还有一个具体的 P2:五秒取消信号能够到达 managed worker,但 local bypass/full-access 路径没有把它传进 nodeGlob。遇到缓慢或不可用的网络挂载时,一次提交可能远远超过预期时间仍无法结束。采用更小的纯路径方案后,也不再需要这套 admission-time timeout。
这是一个收敛实现的建议,并不是建议另建一套并行方案。无论最终选择哪种方式,目录引用都应该保持为唯一 authority。
本次审查分析由 Codex 和独立的 @reviewer 子代理协助;Astro-Han 评估了 authority 边界、问题可达性和简化方案,并对这条评论负责。
…irectory-references
…irectory-references # Conflicts: # packages/runtime-host/src/protocol/index.ts
Summary
Fixes #3994.
This PR separates the composer’s “Add files or directories” entry into “Add files” and “Reference folder”, with a native folder picker and removable folder-reference chips.
Before
After
Review focus
Directory selection adds a reference, not a recursive upload or a permission grant. Listing follows the existing filesystem boundary; inaccessible directories are reported as requiring access or unavailable, rather than silently treated as empty.
Preparation is limited to 100 entries per directory, a shared 8 KiB serialized-entry budget, and a five-second timeout. Timeout, cancellation, foreign-host references, and unsupported external execution are handled without turning expected preparation failures into a Runtime Host drain.
The implementation spans the Desktop picker/composer, message contracts, Runtime Host admission, runtime directory preparation, and persistence/rendering. After merging main at
3b9a4706b, Runtime Host compatibility advances from 61 to 62, so Desktop and Runtime Host must be updated together.Supporting test changes close SQLite fixture stores before cleanup and handle platform-specific symlink and
/proc/self/fdassumptions. Generated source/test inventories are updated; local verification notes and build artifacts are not included.Verification
Unless noted otherwise, these results apply to head
aa342d561304c7604ae7cb36751e86686901d863.macOS
--repeat-each=10, covering removal, send/reload persistence, bounded listing, and unchanged project selection.check:releasepassed, including 110 tests.Windows — local verification
Environment: Node.js
25.2.1, npm11.12.1, Cargo1.98.0.npm ciandnpm run buildcompleted successfully.EBUSYerror or residual Broker/worker processes were observed.Earlier full local Windows regression, packaging, and manual-acceptance records apply to
f6f9c04fbdd73640038f178831cd7e52df3c5788. They are not counted as a complete local rerun on the current head.GitHub Actions
Validation limitations
Local adjacent E2E:
deleting the session while a toggle is pending settles cleanfailed because the sidebar still contained one session row after the ten-second wait. The same assertion also failed on unmodified main at3b9a4706b; two baseline runs produced one failure and one pass. This shows that the failure is not unique to this branch, but its root cause remains unidentified. The full local Desktop E2E matrix was not rerun after the merge.Hosted Windows W0: all four smoke cases passed, but suite teardown failed with
EBUSYwhile removing the temporaryPrograms\Maka\node.exe. The locking process has not been identified, and no successful hosted rerun has been recorded. The six successful local runs used a different toolchain from W0’s Node.js24.19.0/ npm11.17.0, so they do not establish that the hosted failure is resolved. A maintainer rerun of the failed W0 job is needed.AI use
Tool(s) and scope: OpenAI Codex assisted with source inspection, implementation, regression tests, local verification, code review, and drafting this PR. I have reviewed the changes and take responsibility for this contribution.
Checklist
Does this PR entail a change in behavior?